/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Database;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
/**
 *
 * @author Zen
 */

public class Database implements Serializable
{
    private List<Table> tables;
    private String address;
    private String name;
    
    public Database(String name)
    {
	this.name = name;
        address = "Data/" + name + ".data";
        tables = new ArrayList<Table>();
    }
    
    public List<Table> getTable() 
    {
        return tables;
    }
   
    public void setTable(List<Table> table) 
    {
        this.tables = table;
    }
    
    public String getAddress() 
    {
        return address;
    }
    
    public String getName() 
    {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        this.address = "Data/" + name + ".data";
    }
	
    //Thêm bảng với tên là tableName
    //chưa có cột
    public boolean AddTable(String tableName)
    {
        for(int i=0;i<tables.size();i++)
            if(tables.get(i).getName().toLowerCase().equals(tableName.toLowerCase()))
                return false;
        tables.add(new Table(tableName));
        return true;
    }
    public int getTableIndex(String tableName)
    {
        for(int i=0;i<tables.size();i++)
        {  
            if(tables.get(i).getName().toLowerCase().equals(tableName.toLowerCase()))
                return i;
        }
        return -1;
    }
    public boolean IsHasForeignKeyToTable(String tableName)
    {
        for(int i=0;i<tables.size();i++)
        {
            for(int j=0;j<tables.get(i).getForeignKey().size();j++)
            {
                if(tables.get(i).getForeignKey().get(j).getPkTable().toLowerCase().equals(tableName.toLowerCase()))
                {
                    return true;
                }
            }
        }
        return false;
    }
    
    public boolean AddPrimaryKeyColumn(String colName,String tableName)
    {
        if(IsHasForeignKeyToTable(tableName))
            return false;
        int tableIdx = getTableIndex(tableName);
        return tables.get(tableIdx).addPKColumn(colName);
    }
    public boolean RemovePrimaryKeyColumn(String colName,String tableName)
    {
        if(IsHasForeignKeyToTable(tableName))
            return false;
        int tableIdx = getTableIndex(tableName);
        return tables.get(tableIdx).removePKColumn(colName);        
    }
    public boolean RemovePrimaryKey(String tableName)
    {
        if(IsHasForeignKeyToTable(tableName))
            return false;
        int tableIdx = getTableIndex(tableName);
        tables.get(tableIdx).removePrimaryKey();        
        return true;
    }
    public boolean RemoveForeignKey(String fkKeyName, String tableName)
    {
        int fkTableIdx = getTableIndex(tableName);
        return tables.get(fkTableIdx).removeElementForeginKey(fkKeyName);        
    }    
    //Thêm khóa ngoại
    public boolean AddForeignKey(ForeignKey fk,String fkTableName)
    {
        int fkTableIdx = getTableIndex(fkTableName);
        int pkTableIdx = getTableIndex(fk.getPkTable());        
        if(fk.getFkColumns().size()!=fk.getPkColumns().size()||fkTableIdx==-1||pkTableIdx==-1)
            return false;
        for(int i=0;i<fk.getFkColumns().size();i++)
        {
            int fkColIdx= tables.get(fkTableIdx).getColumnIndex(fk.getFkColumns().get(i));
            int pkColIdx= tables.get(pkTableIdx).getColumnIndex(fk.getPkColumns().get(i));
            if(fkColIdx==-1||pkColIdx==-1)
            {
                return false;
            }
            else
            {
                if(tables.get(fkTableIdx).getColumns().get(fkColIdx).getType()!=
                        tables.get(pkTableIdx).getColumns().get(pkColIdx).getType())
                    return false;
            }
            return (tables.get(fkTableIdx).addElementForeignKey(fk));  
        }                  
        return false;
    }
    public boolean CheckForeignKey(Table table, List<Object> dataRow )
    {
        if(table.getForeignKey().size()>0)
        {
            for(int i=0;i<table.getForeignKey().size();i++)
            {                
                ForeignKey fk = table.getForeignKey().get(i);
                int pkTableIdx = getTableIndex(fk.getPkTable());                
                Table pkTable = tables.get(pkTableIdx);
                List<Object> fkData= new ArrayList<Object>();
                for(int j=0;j<dataRow.size();j++)
                {
                    for(int e=0;e<fk.getFkColumns().size();e++)
                    {
                        if(table.getColumns().get(j).getName().toLowerCase().equals(fk.getFkColumns().get(e).toLowerCase()))
                        {
                            fkData.add(dataRow.get(j));
                        }
                    }
                }
                if(!pkTable.IsValidForeingKey(fkData,fk.getPkColumns()))
                    return false;
            }            
        }
        return true;
    }
    public boolean InsertRow(List<Object> dataRow, String tableName)
    {
        int tableIdx = getTableIndex(tableName);
        Table table = tables.get(tableIdx);
        //Kiểm tra khóa ngoại
        if(!CheckForeignKey(table,dataRow))
            return false;
        return table.InsertRow(dataRow);
    }
    public boolean SetData(int rowIdx, List<Object> dataRow, String tableName)
    {
        int tableIdx = getTableIndex(tableName);
        Table table = tables.get(tableIdx);
        //Kiểm tra khóa ngoại
        if(!CheckForeignKey(table,dataRow))
            return false;
        return table.SetData(rowIdx, dataRow);
    }
    public boolean SetData(int row, int col,  Object newValue, String tableName)
    {
        int tableIdx = getTableIndex(tableName);
        Table table = tables.get(tableIdx);
        int nCols=table.getColumns().size();        
        List<Object> dataRow = new ArrayList<Object>();
        for(int i=0;i<nCols;i++)
        {
            dataRow.add(table.getColumns().get(i).getData().get(row));                   
        }
        dataRow.set(col, newValue);
        //Kiểm tra khóa ngoại
        if(!CheckForeignKey(table,dataRow))
            return false;
        return table.SetData(row, dataRow);
    }
    //xóa bảng có tên là tableName
    public boolean RemoveTable(String tableName)
    {
         for(int i=0;i<tables.size();i++)
            if(tables.get(i).getName().toLowerCase().equals(tableName.toLowerCase()))
            {
                tables.remove(i);
                return true;
            }
        return false;
    }    
    
    //Kiểm tra tồn tại bảng có tên tableName chưa
    public boolean IsExistTable(String tableName)
    {
        for(int i=0;i<tables.size();i++)
            if(tables.get(i).getName().toLowerCase().equals(tableName.toLowerCase()))
            {
                return true;
            }
        return false;
    }
    
    //Save database
    public boolean Save() 
    { 
        try
        {
            FileOutputStream fos = new FileOutputStream(address);                
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(this);
            oos.close();
            return true;
        }catch (IOException cnfe)
        {
            return false;
        }      
    }
    
    public boolean Rename(String databaseName)
    {
        File fileSrc = new File(this.address);
        this.name = databaseName;
        this.address = "Data/" + databaseName + ".data";        
        if(fileSrc.exists())
        {
            File fileDest = new File(address);
            return fileSrc.renameTo(fileDest);
        }
        return true;
    }
    
    public void Delete()
    {
        File file = new File(this.address);
        file.delete();
    }
    
}

